home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / unix / src / dir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-28  |  3.4 KB  |  174 lines

  1. #include "amiga.h"
  2. #include "dir_data.h"
  3. #include <string.h>
  4.  
  5. /* opendir/readdir/etc ... emulation w/ stat support hack */
  6.  
  7. static void free_entries(iDIR *info)
  8. {
  9.   struct idirect *scan = info->files;
  10.   
  11.   while (scan)
  12.     {
  13.       struct idirect *next = scan->next;
  14.       
  15.       free(scan);
  16.       scan = next;
  17.     }
  18. }
  19.  
  20. static int gobble_dir(DIR *dir)
  21. {
  22.   iDIR *info = (iDIR *)dir->dd_buf;
  23.   long ioerr;
  24.   struct idirect **last = &info->files;
  25.   
  26.   free_entries(info);
  27.   last_info = 0;
  28.   info->files = 0;
  29.   dir->dd_loc = 0;
  30.   while (ExNext(dir->dd_fd, &info->fib))
  31.     {
  32.       u_short namlen = strlen(info->fib.fib_FileName);
  33.       u_short reclen = namlen + 1 + offsetof(struct idirect, entry.d_name);
  34.       struct idirect *newentry = (struct idirect *)malloc(reclen);
  35.       struct direct *entry;
  36.       
  37.       if (!newentry)
  38.     {
  39.       errno = ENOMEM;
  40.       return 0;
  41.     }
  42.       newentry->next = 0;
  43.       *last = newentry;
  44.       last = &newentry->next;
  45.       
  46.       newentry->numblocks = info->fib.fib_NumBlocks;
  47.       newentry->size = info->fib.fib_Size;
  48.       newentry->date = info->fib.fib_Date;
  49.       newentry->type = info->fib.fib_DirEntryType;
  50.       newentry->protection = info->fib.fib_Protection;
  51.       
  52.       entry = &newentry->entry;
  53.       entry->d_ino = info->fib.fib_DiskKey;
  54.       entry->d_reclen = reclen;
  55.       entry->d_namlen = namlen;
  56.       entry->d_off = dir->dd_loc++;
  57.       strcpy(entry->d_name, info->fib.fib_FileName);
  58.     }
  59.   info->pos = info->files;
  60.   dir->dd_loc = 0;
  61.   ioerr = IoErr();
  62.   if (ioerr == ERROR_NO_MORE_ENTRIES) return 1;
  63.   
  64.   errno = convert_oserr(ioerr);
  65.   return 0;
  66. }
  67.  
  68. DIR *opendir(char *dirname)
  69. {
  70.   DIR *new = (DIR *)malloc(sizeof *new);
  71.   iDIR *info = (iDIR *)malloc(sizeof *info);
  72.   char *dircopy = malloc(strlen(dirname) + 1);
  73.  
  74.   chkabort();
  75.   if (new && dircopy && info)
  76.     {
  77.       new->dd_buf = (char *)info;
  78.       new->dd_size = sizeof *info;
  79.       
  80.       info->files = info->pos = 0;
  81.       info->seeked = 0;
  82.       info->dirname = dircopy;
  83.       strcpy(dircopy, dirname);
  84.       info->cdir = _get_cd();
  85.       
  86.       if ((new->dd_fd = Lock(dirname, ACCESS_READ)) &&
  87.       Examine(new->dd_fd, &info->fib))
  88.     {
  89.       if (gobble_dir(new)) return new;
  90.     }
  91.       else errno = convert_oserr(IoErr());
  92.       closedir(new);
  93.       return 0;
  94.     }
  95.   
  96.   errno = ENOMEM;
  97.   if (new) free(new);
  98.   if (dircopy) free(dircopy);
  99.   if (info) free(info);
  100.   
  101.   return 0;
  102. }
  103.  
  104. void closedir(DIR *dir)
  105. {
  106.   iDIR *info = (iDIR *)dir->dd_buf;
  107.   
  108.   chkabort();
  109.   last_info = 0;
  110.   free_entries(info);
  111.   free(info->dirname);
  112.   if (dir->dd_fd) UnLock(dir->dd_fd);
  113.   free(dir->dd_buf);
  114.   free(dir);
  115. }
  116.  
  117. struct direct *readdir(DIR *dir)
  118. {
  119.   iDIR *info = (iDIR *)dir->dd_buf;
  120.   struct direct *entry = 0;
  121.   
  122.   chkabort();
  123.   if (info->seeked)
  124.     {
  125.       long cloc = 0;
  126.       struct idirect *pos;
  127.       
  128.       pos = info->files;
  129.       
  130.       while (cloc < dir->dd_loc && pos)
  131.     {
  132.       cloc++; pos = pos->next;
  133.     }
  134.       /*if (cloc != dir->dd_loc) error ...
  135.     This doesn't seem to be defined very precisely */
  136.       info->pos = pos;
  137.       info->seeked = 0;
  138.     }
  139.   if (info->pos)
  140.     {
  141.       entry = &info->pos->entry;
  142.       
  143.       last_info = info;
  144.       last_entry = info->pos;
  145.       
  146.       info->pos = info->pos->next;
  147.       dir->dd_loc++;
  148.     }
  149.   return entry;
  150. }
  151.  
  152. long telldir(DIR *dir)
  153. {
  154.   chkabort();
  155.   return dir->dd_loc;
  156. }
  157.  
  158. void seekdir(DIR *dir, long loc)
  159. {
  160.   iDIR *info = (iDIR *)dir->dd_buf;
  161.   
  162.   chkabort();
  163.   info->seeked = 1;
  164.   dir->dd_loc = loc;
  165. }
  166.  
  167. #if 0
  168. void rewwinddir(DIR *dir)
  169. {
  170.   chkabort();
  171.   gobble_dir(dir);
  172. }
  173. #endif
  174.